package chu.dejian.ui.fragmet;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.widget.TextView;

import org.achartengine.chart.AbstractChart;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.sam.ble.unimplements.BLEBRHelper;
import com.sam.blemodule.R;

import chu.dejian.conf.BLEPreference;
import chu.dejian.db.DBHelper;
import chu.dejian.dialogOrMenu.DayRecordsDialog;
import chu.dejian.entity.RecordEntity;
import chu.dejian.models.GetMeasurementResponse;
import chu.dejian.restApi.RestClient;
import com.sam.dialog.LoadingDialog;
import com.sam.ui.base.fragment.BaseFragment;
import com.sam.utils.L;
import com.sam.utils.NetUtil;
import com.sam.utils.T;
import chu.dejian.widget.ViewPagerNavBar;
import chu.dejian.widget.chartView.BPChartView;
import chu.dejian.widget.chartView.BaseBPChartUtils;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;

public class RecordChartFragment extends BaseFragment {
	private static RecordChartFragment instance;
	private ViewPagerNavBar navBar;
	private ViewPager viewpager;
	private TextView shrinkageValueTV,diastolicValueTV,pulseValueTV,recordTime,rhythmValueTV;
	private View rightArrow,leftArrow,dayRecordsBtn,seekAdviceBtn;
	private int curRecordIndex;
	private DayRecordsDialog dayRecordsDialog;
	BPChartView dayChartView,monthChartView,threeMonthChartView;
	BPChartView currentChartView;
	List<RecordEntity> currShownRecords;
	private View referenceBtn;
	LoadingDialog loadingDialog;

	public synchronized static RecordChartFragment getInstance(){
		if(instance == null){
			instance = new RecordChartFragment();
		}
		return instance;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.fragment_record_chart);
		if(loadingDialog == null) loadingDialog = new LoadingDialog(getActivity(),getString(R.string.synchronizing_record));
	}

	public void findView() {
		navBar = (ViewPagerNavBar) findViewById(R.id.nav_bar);
		viewpager = (ViewPager) findViewById(R.id.record_view_pager);
		dayRecordsBtn = findViewById(R.id.day_record_details);
		leftArrow = findViewById(R.id.left_arrow);
		rightArrow = findViewById(R.id.right_arrow);
		shrinkageValueTV = (TextView) findViewById(R.id.shrinkage_value);
		diastolicValueTV = (TextView) findViewById(R.id.diastolic_value);
		pulseValueTV = (TextView) findViewById(R.id.pulse_value);
		recordTime = (TextView) findViewById(R.id.record_time);
		seekAdviceBtn = findViewById(R.id.seek_medical_advice);
		rhythmValueTV = (TextView) findViewById(R.id.rhythm_value);
		referenceBtn = findViewById(R.id.reference_table);
	}


	@Override
	public void onResume() {
		super.onResume();
		if(NetUtil.checkNetWork(getActivity())) ansyncMeasureRecordThread.start();
		navBar.resetCursorLine();
	}

	@Override
	public void onDestroyView() {
		if(loadingDialog != null){
			if(loadingDialog.isShowing()) loadingDialog.dismiss();
			loadingDialog = null;
		}
		super.onDestroyView();
	}

	private int size = 0;
	private synchronized void refreshRecord(){
		final List<RecordEntity> recordEntityList = DBHelper.getInstance().getRecordDao().getAllRecord();
		if(size == recordEntityList.size()) return;
		size = recordEntityList.size();
		dayChartView.setRecordEntityList(recordEntityList, BPChartView.DISPLAY_TYPE.DAY);
		monthChartView.setRecordEntityList(recordEntityList, BPChartView.DISPLAY_TYPE.THREE_MONTH);
		threeMonthChartView.setRecordEntityList(recordEntityList, BPChartView.DISPLAY_TYPE.THREE_MONTH);
		try{
			currShownRecords = currentChartView.getShownRecordList();
			viewRecord(currShownRecords.get(curRecordIndex));
			checkArrowState();
		} catch (Exception e){
			L.e("同步记录后更新界面出现异常");
		}

	}

	public void initView() {
//		loadingDialog = new CustomLoadingDialog.Builder(getActivity()).setMessage(getString(R.string.synchronizing_record)).create();
		dayChartView = new BPChartView(getActivity());
		monthChartView = new BPChartView(getActivity());
		threeMonthChartView = new BPChartView(getActivity());

		final List<RecordEntity> recordEntityList = DBHelper.getInstance().getRecordDao().getAllRecord();
		size = recordEntityList.size();
		dayChartView.setShowPoint(true);
		dayChartView.setLineColor(getResources().getColor(R.color.gray_text_color));
		dayChartView.setChartStyle(BaseBPChartUtils.CHART_STYLE.LINE);
		dayChartView.setRecordEntityList(recordEntityList, BPChartView.DISPLAY_TYPE.DAY);
		currentChartView = dayChartView;
		currShownRecords = currentChartView.getShownRecordList();
		viewRecord((currShownRecords == null || currShownRecords.size() == 0) ? null : currShownRecords.get(0));

		monthChartView.setShowPoint(false);
		monthChartView.setLineColor(getResources().getColor(R.color.main_blue_color));
		monthChartView.setRecordEntityList(recordEntityList, BPChartView.DISPLAY_TYPE.MONTH);

		threeMonthChartView.setShowPoint(false);
		threeMonthChartView.setLineColor(getResources().getColor(R.color.main_blue_color));
		threeMonthChartView.setRecordEntityList(recordEntityList, BPChartView.DISPLAY_TYPE.THREE_MONTH);

		final List<View> pages = new ArrayList<View>(Arrays.asList(dayChartView,monthChartView,threeMonthChartView));
		for(View view : pages){
			final BPChartView chartView = (BPChartView)view;
			chartView.setRecordPointClickListener(new BPChartView.RecordPointClickListener() {
				@Override
				public void onRecordPointClicked(RecordEntity recordEntity, int pointIndex, int pointValue) {
					curRecordIndex = pointIndex;
					viewRecord(recordEntity);
					checkArrowState();
					if(dayRecordsDialog == null) dayRecordsDialog = new DayRecordsDialog(getActivity());
					dayRecordsDialog.setDayRecords(chartView.getGroupedRecordLists().get(pointIndex));
					if(!dayRecordsDialog.isShowing()) dayRecordsDialog.show();
				}
			});
			chartView.setOnChartItemClickListener(new AbstractChart.ChartItemClickListener() {
				@Override
				public void onChartItemClick(double position) {
					if(position < 0 || currShownRecords == null || position >= currShownRecords.size()) return;
					curRecordIndex = (int)position;
					RecordEntity recordEntity = currShownRecords.get(curRecordIndex);
					if(recordEntity == null) T.showShort(getActivity(),getActivity().getString(R.string.no_records_in_that_day));
					else {
						viewRecord(recordEntity);
						checkArrowState();
//						if(dayRecordsDialog == null) dayRecordsDialog = new DayRecordsDialog(getActivity());
//						dayRecordsDialog.setDayRecords(chartView.getGroupedRecordLists().get(curRecordIndex));
//						if(!dayRecordsDialog.isShowing()) dayRecordsDialog.show();
					}
				}
			});
		}
		navBar.setPages(viewpager, pages);
		navBar.setOnPageChangeCallback(new ViewPagerNavBar.OnPageChangeCallback() {
			@Override
			public void onPageChanged(int position) {
				currentChartView = (BPChartView) pages.get(position);
				currShownRecords = currentChartView.getShownRecordList();
				if(currShownRecords == null || currShownRecords.size() == 0) viewRecord(null);
				else {
					int i = 0;
					while(i < currShownRecords.size() - 1 && currShownRecords.get(i) == null) i++;
					viewRecord(currShownRecords.get(i));
				}
			}
		});
		dayRecordsBtn.setOnClickListener(onClickListener);
		leftArrow.setOnClickListener(onClickListener);
		rightArrow.setOnClickListener(onClickListener);
		seekAdviceBtn.setOnClickListener(onClickListener);
		referenceBtn.setOnClickListener(onClickListener);
	}

	private void checkArrowState(){
		if(currShownRecords == null || currShownRecords.size() == 0) return;
		if(currShownRecords.size() < 2) {
			leftArrow.setVisibility(View.INVISIBLE);
			rightArrow.setVisibility(View.INVISIBLE);
		} else {
			leftArrow.setVisibility(View.VISIBLE);
			rightArrow.setVisibility(View.VISIBLE);
			if(curRecordIndex == 0) {
				leftArrow.setVisibility(View.INVISIBLE);
			}
			if(curRecordIndex == currShownRecords.size() - 1){
				rightArrow.setVisibility(View.INVISIBLE);
			}
		}

	}

	private View.OnClickListener onClickListener = new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			int i = v.getId();
			if (i == R.id.day_record_details) {
				if (dayRecordsDialog == null)dayRecordsDialog = new DayRecordsDialog(getActivity());
				dayRecordsDialog.setDayRecords(currentChartView.getGroupedRecordLists().get(curRecordIndex));
				if (!dayRecordsDialog.isShowing()) dayRecordsDialog.show();

			} else if (i == R.id.left_arrow) {
				if (currShownRecords == null || currShownRecords.size() == 0) return;
				currentChartView.focusePreviousItem();
				curRecordIndex--;
				checkArrowState();

			} else if (i == R.id.right_arrow) {
				if (currShownRecords == null || currShownRecords.size() == 0) return;
				currentChartView.focuseNextRecord();
				curRecordIndex++;
				checkArrowState();

			} else if(i == R.id.seek_medical_advice){
				BLEBRHelper.getInstance().sendSeekAdviceBR(getActivity());
			} else if(i == R.id.reference_table){
				replaceSelfWithFragment(ReferenceTableFragment.getInstance());
			}
		}
	};


	private void viewRecord(RecordEntity recordEntity){
		if(recordEntity == null) {
			recordTime.setText(R.string.no_record_data);
			shrinkageValueTV.setText("-");
			diastolicValueTV.setText("-");
			pulseValueTV.setText("-");
			dayRecordsBtn.setVisibility(View.GONE);
		} else {
			recordTime.setText(new SimpleDateFormat(getResources().getString(R.string.message_time_format)).format(recordEntity.getMeasureDateTime()));
			shrinkageValueTV.setText(recordEntity.systolic+"");
			diastolicValueTV.setText(recordEntity.diastolic+"");
			pulseValueTV.setText(recordEntity.pulse +"");
			rhythmValueTV.setText(recordEntity.pulseState == 1 ? R.string.arrhythmia : R.string.normal);
			dayRecordsBtn.setVisibility(View.VISIBLE);
		}
	}


	//===========================================================================================
	//             下载测量记录
	//===========================================================================================
	private List<RecordEntity> recordEntityList = DBHelper.getInstance().getRecordDao().getAllRecord();
	private AnsyncMeasureRecordThread ansyncMeasureRecordThread = new AnsyncMeasureRecordThread();
	private static final int REFRESH_RECORD = 0;
	private static final int ALERT_MESSAGE = 1;
	private static final int ALERT_LOADING_DIALOG = 2;
	private static final int CLOSE_LOADING_DIALOG = 3;
	private Handler handler = new Handler(){
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what){
				case REFRESH_RECORD:
					refreshRecord();
					break;
				case ALERT_MESSAGE:
					T.showLong(getActivity(),(String)msg.obj);
					break;
				case ALERT_LOADING_DIALOG:
//					loadingDialog.show();
					break;
				case CLOSE_LOADING_DIALOG:
//					loadingDialog.dismiss();
					break;
			}
			super.handleMessage(msg);
		}
	};
	private synchronized void ansyncMeasureRecord(){
		final int page = BLEPreference.getInstance().getMeasurementPage();
		RestClient.getAuthedClient().getApiService().getMeasurement(page, new Callback<GetMeasurementResponse>(){

			@Override
			public void success(GetMeasurementResponse getMeasurementResponse, Response response) {
				if(response.getStatus() == 401) {
					BLEBRHelper.getInstance().sendReloginBR(getActivity());
					T.showShort(getActivity(),R.string.nauthorized_and_relogin);
					return;
				}
				L.d("《获取测量记录-getMeasurement》" + "\n" + "请求成功： \n\t返回数据：" + getMeasurementResponse.toString());
				List<GetMeasurementResponse.ResultsEntity> recordEntities = getMeasurementResponse.getResults();
				if(recordEntities == null || recordEntities.size() == 0) return;
				List<RecordEntity> res = new ArrayList<RecordEntity>();
				for(GetMeasurementResponse.ResultsEntity recordEntity : recordEntities){
					GetMeasurementResponse.ResultsEntity.ResultEntity measurement = recordEntity.getResult();
					if(measurement != null && measurement.getSystolic() != 0 && measurement.getDiastolic() != 0 && measurement.getPulse() != 0){
						RecordEntity re = new RecordEntity(measurement.getSystolic(),measurement.getDiastolic(),measurement.getPulse(),recordEntity.getTime());
						re.pulseState = measurement.getPulsestate();
						re.message = measurement.getMessage();
						re.note = measurement.getNote();
						re.isUploaded = true;
						res.add(re);
					}
				}
				if(res.size() > 0){
					res.removeAll(recordEntityList);  // 移除已经存储过的记录
					for(RecordEntity re : res){
						DBHelper.getInstance().getRecordDao().insertRecord(re);
					}
					recordEntityList.addAll(res);
				}
				if(getMeasurementResponse.getNext() != null && !getMeasurementResponse.getNext().equals("null")){
					BLEPreference.getInstance().setMeasurementPage(page+1);
					ansyncMeasureRecord();
				} else if(recordEntityList.size() > 0) {
					Message msg = new Message();
					msg.what = REFRESH_RECORD;
					handler.sendMessage(msg);
				}
			}

			@Override
			public void failure(RetrofitError retrofitError) {
				L.d("《获取测量记录-getMeasurement》"+"\n"+ "请求失败： \n\t错误信息：" + retrofitError.toString());
//				T.showLong(getActivity(),R.string.measure_record_ansync_failed);
				Message msg = new Message();
				msg.what = ALERT_MESSAGE;
				msg.obj = getResources().getString(R.string.measure_record_ansync_failed);
				handler.sendMessage(msg);
			}
		});
	}




	class AnsyncMeasureRecordThread implements Runnable {
		public boolean running = false;
		private Thread thread = null;
		private static final long DIALOG_MIN_SHOW_MILLIS = 1500; // 至少显示1.5秒的加载框
		long startTime= 0L;
		private void closeDialog(){
			long lastTime = System.currentTimeMillis() - startTime;
			if(lastTime < 1500){
				try {
					Thread.sleep(DIALOG_MIN_SHOW_MILLIS);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			Message msg = new Message();
			msg.what = CLOSE_LOADING_DIALOG;
			handler.sendMessage(msg);
		}

		public void run() {
			ansyncMeasureRecord();
			closeDialog();
		}

		public void start() {
			startTime = System.currentTimeMillis();
			Message msg = new Message();
			msg.what = ALERT_LOADING_DIALOG;
			handler.sendMessage(msg);
			this.thread = new Thread(this);
			this.running = true;
			this.thread.start();
		}

		public void stop() {
			this.running = false;
			this.thread = null;
		}
	}

}
